using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using xjjxmm.infrastructure.Authorizations;
using XjjXmm.Infrastructure.Configuration;
using XjjXmm.Infrastructure.Constant;
using XjjXmm.Infrastructure.Exceptions;
using xjjxmm.infrastructure.ToolKit;
using XjjXmm.Infrastructure.User;
using System.Reflection;
using System;
using XjjXmm.Infrastructure.Common;
using XjjXmm.Infrastructure.ToolKit;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using xjjxmm.infrastructure.Webs;
using xjjxmm.infrastructure.xjjxmmLog.LogKit;
using System.Text;
using System.Diagnostics;

namespace xjjxmm.infrastructure.Middleware;

public class HttpRequestLogMiddleware : IMiddleware
{
   
    private readonly ILog<HttpRequestLogMiddleware> _log;
    
    public HttpRequestLogMiddleware(ILog<HttpRequestLogMiddleware> log)
    {
        _log = log;
       
    }

    public async Task InvokeAsync(HttpContext httpContext, RequestDelegate next)
    {
           if(httpContext.Request.Path.ToString().Contains("."))
        {
           await next(httpContext);
           return;
        }

           if(httpContext.Request.Method.ToUpper() == "OPTIONS") {
            await next(httpContext);
            return;
        }
        //var fPath = httpContext.Request.Path.ToString().ToLower().Split('.').LastOrDefault();
        //var exclued = new string[]{ "html", "json", "jpg", "png" };

        //if (exclued.Contains(fPath))
        //{
        //    await next(httpContext);
        //    return;
        //}

           var sw = new Stopwatch();
        sw.Start();

        var originalBody = httpContext.Response.Body;
        try
        {
            var id = Guid.NewGuid();
            httpContext.Request.EnableBuffering();
            var stream = httpContext.Request.Body;


            using var reader = new StreamReader(stream, Encoding.UTF8, true, 1024, true);

            var body = await reader.ReadToEndAsync();
            var headers = httpContext.Request.Headers.Select(x => x.Key + " = " + x.Value);
            var sb = new StringBuilder();
            sb.AppendLine($"{Environment.NewLine}========================================== Http Log Start ==========================================");
            sb.AppendLine($"request: {id}");
            sb.AppendLine($"path: {httpContext.Request.Path}{httpContext.Request.QueryString}");
            sb.AppendLine($"method: {httpContext.Request.Method}");
            sb.AppendLine("header: ");
            foreach (var item in headers)
            {
                sb.AppendLine(item);
            }
            //sb.AppendLine($"body: {body}");
            _log.Information(sb.ToString());
            _log.Information($"body: {body}");

            httpContext.Request.Body.Position = 0;


            using MemoryStream ms = new MemoryStream();
            httpContext.Response.Body = ms;

            await next(httpContext);

            ms.Position = 0;
            //await httpContext.Response.Body.CopyToAsync(response);
            //response.Seek(0, SeekOrigin.Begin);

            using var responseReader = new StreamReader(ms, Encoding.UTF8);

            var respBody = await responseReader.ReadToEndAsync();
            _log.Information($"response: {id}" +
                 $"{Environment.NewLine}status code: {httpContext.Response.StatusCode}");

            _log.Debug($"body: {respBody}");

            ms.Position = 0;
            await ms.CopyToAsync(originalBody);

            //httpContext.Response.Body = originalBody;
        }
        finally
        {
            //无论异常与否都要把原始的Body给切换回来
            httpContext.Response.Body = originalBody;
            sw.Stop();
            _log.Debug($"耗时: {sw.Elapsed.TotalSeconds}s" +
                 $"{Environment.NewLine}========================================== Http Log End ==========================================");
        }
    }
}